package org.vanjor.bitmap;

import java.lang.reflect.Array;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Class
 * 
 * @author Vanjor
 * 
 * 
 */
public class BitMap {

	// 存储BitMap的数组
	private byte[] array = null;

	// int max is 2147483648,max use 256MB menory
	private int size = 0;

	private Integer filledCount = 0;

	// 默认大小
	private static final int DEFAULT_SIZE = 1024;

	// 与计算，置对应位0
	private static final byte[] AND_SET_ZERO = { (byte) 0xfe, (byte) 0xfd,
			(byte) 0xfb, (byte) 0xf7, (byte) 0xef, (byte) 0xdf, (byte) 0xbf,
			(byte) 0x7f };
	// 或计算，置对应位1
	private static final byte[] OR_SET_ONE = { (byte) 0x01, (byte) 0x02,
			(byte) 0x04, (byte) 0x08, (byte) 0x10, (byte) 0x20, (byte) 0x40,
			(byte) 0x80 };

	private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

	private final Lock w = rwLock.writeLock();

	private final Lock r = rwLock.readLock();

	/**
	 * 无参构造函数，大小为默认DEFAULT_SIZE大小
	 */
	public BitMap() {
		this(DEFAULT_SIZE);
	}

	/**
	 * 参构造函数 
	 * @param size
	 *             为指定BitMap大小，构造后不可改变
	 */
	public BitMap(int size) {
		// 如果为负数，则重置为默认大小
		if (size <= 0) {
			size = DEFAULT_SIZE;
		}
		this.size = size;
		array = (byte[]) Array.newInstance(byte.class, size / 8 + 1);
	}

	/**
	 * Map的put方法，往BitMap中对应位置插入值,
	 * 
	 * @param index
	 *              对应BitMap位置
	 * @param value
	 *              true表示置为1，false表示置为0
	 * @return 
	 *        false 表示失败，true表示成功
	 */
	public boolean put(int index, boolean value) {
		w.lock();
		try {
			// 把bit的下标转换为 byte下标 和 游标
			int byteIndex = index / 8;
			int cursor = index % 8;
			byte temp = array[byteIndex];
			if (value == true) {
				temp = (byte) ((byte) temp | OR_SET_ONE[cursor]);
				synchronized (filledCount) {
					filledCount++;
				}
			} else {
				temp = (byte) ((byte) temp & AND_SET_ZERO[cursor]);
				synchronized (filledCount) {
					filledCount--;
				}
			}
			array[byteIndex] = temp;
			return true;
		} catch (Throwable e) {
			e.printStackTrace();
			return false;
		} finally {
			w.unlock();
		}
	}

	/**
	 * * Map的get方法，从BitMap中返回对应位置值,
	 * @param index
	 *             对应查找位置
	 * @return
	 *         返回true 或 false ，true为标记1，false为标记0
	 */
	public boolean get(int index) {
		r.lock();
		try {
			// 把bit的下标转换为 byte下标 和 游标
			int byteIndex = index / 8;
			int cursor = index % 8;
			byte temp = array[byteIndex];
			return ((byte) (temp >> cursor) & 0x1) > 0 ? true : false;
		} catch (Throwable e) {
			e.printStackTrace();
			return false;
		} finally {
			r.unlock();
		}
	}

	/**
	 * 返回BitMap的大小
	 * 
	 * @return
	 *        BitMap的容量
	 */
	public int size() {
		return size;
	}

	/**
	 * 返回当前装载量，也就是填满1的数量
	 * 
	 * @return
	 *        BitMap的装载量
	 */
	public int getFilledCount() {
		return filledCount;
	}
}